\documentclass[a4paper]{article}
\usepackage[dutch]{babel}
\usepackage[latin1]{inputenc}
\usepackage{bbm}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage[top=3cm,left=3cm,right=3cm,bottom=2cm,foot=1cm]{geometry}
\renewcommand{\thesection}{\arabic{section}}

\title{\textbf{Practicum Codesign Project} \\ Communicatie tussen processen via sockets}
\author{{\bf J.H. Donker} \and {\bf J. Teeuw}}

\begin{document}
\maketitle

%\begin{abstract}
%Summary
%\end{abstract}

\section*{Eerste opdracht: C-code begrijpen}

\subsection*{Symbolen}
\begin{description}
\item[{\bf *}] Het sterretje (\verb|*|) wordt gebruikt bij typering van variablen om aan te geven dat het om een pointer naar het type gaat. Voor de naam van een variabel van het type pointer naar een datastructuur wordt met het sterretje aangegeven dat de inhoud waar de pointer heen wijst geadresseerd moet worden. Dit laatste wordt ook wel \verb|dereferencing| genoemd.
\item[{\bf \&}] De ampersand (\verb|&|) wordt gebruikt om het geheugenadres van een datastructuur op te vragen.
\item[{\bf -$>$}] Deze operator is vergelijkbaar aan de \verb|dereference| operatie van het sterretje. Om deze manier kunnen gemakkelijk de eigenschappen van een datastructuur geadresseerd worden. De operatie is vergelijkbaar aan een \verb|dereference| gevolgd door de punt (\verb|.|) operator.
\item[{\bf void}] Void betekend niets, leeg. Een functie dat void als waarde aflevert zal dus in werkelijkheid niets afleveren. Een void pointer is een pointer naar een onbepaald datastructuur.
\end{description}

\subsection*{Datastructuren}
\begin{description}
\item[{\bf struct sockaddr}] Dit datastructuur is het oude datastructuur dat gebruikt werd om gegevens over de socket in op te slaan zoals het adresfamilie, het adres van de socket, het poortnummer, etc. Zie ook {\em struct sockaddr\_in} voor het nieuwere datastructuur.
\item[{\bf struct hostent}] Dit datastructuur bevat de gegevens die verkregen kunnen worden door aanroep van de functie \verb|gethostbyname()|. De datastructuur bevat o.a. het internet adres van de opgevraagde hostnaam.
\item[{\bf struct sockaddr\_in}] Dit datastructuur is later toegevoegd aan de bibliotheek. Het zorgt ervoor dat gegevens over de socket makkelijker adresseerbaar zijn.
\end{description}

\subsection*{Functies}
\begin{description}
\item[{\bf sizeof()}] Deze methode levert de grootte in bytes van een datatype op. Het voorbeeld op lijn 23 in \verb|sockLib.c| levert de grootte in bytes van de \verb|structure sockStruct| op.
\item[{\bf malloc()}] Deze methode reserveert een gegeven aantal bytes geheugen. De methode levert een \verb|void*| op als waarde die verwijst naar het eerste adres van het gereserveerde geheugenruimte.
\item[{\bf socket()}] Deze methode maakt een nieuwe \verb|socket| aan via de systeemaanroepen van het besturingssysteem. De aanroep in het voorbeeld op lijn 27 in \verb|sockLib.c| maakt een nieuwe \verb|TCP/IP socket| aan. De methode levert een \verb|filedescriptor| af naar de gecre\"eerde socket. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\item[{\bf free()}] Deze methode keert het gereserveerde geheugen terug aan het besturingssysteem. Zie ook {\em malloc()}.
\item[{\bf bind()}] Deze methode bindt een gegeven socket aan een internet adres en poort adres waar op geluisterd wordt voor binnenkomende verbindingen. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\item[{\bf listen()}] Deze methode zorgt ervoor dat de socket daadwerkelijk naar inkomende berichten luistert. De extra parameter die meegegeven wordt geeft aan hoeveel binnenkomende verbindingen in de wachtrij kunnen staan voor verbindingen geweigerd worden. Bij problemen wordt een waarde van \verb|-1| opgeleverd. Zie ook {\em accept()}.
\item[{\bf accept()}] Deze methode stagneert de uitvoer tot een verbinding op de socket binnenkomt. De inkomende verbinding wordt van de wachtrij gehaald. Informatie over de verbinding wordt in het doorgegeven \verb|socketStruc| datastructuur opgeslagen. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\item[{\bf htons()}] Deze methode zorgt dat de volgorde van de bits en bytes op de juiste manier geordend worden. De naam van de functie is afgeleid van \verb|host-to-network-short|.
\item[{\bf connect()}] Deze methode zorgt ervoor dat de verbinding met een andere computer tot stand gebracht wordt. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\item[{\bf CreateSocket()}] Deze methode maakt een nieuwe TCP/IP socket aan, zorgt voor foutafhandeling als de socket niet aangemaakt kan worden en levert bij succes een pointer op naar een \verb|sockStruct| met daarin de gegevens over de socket.
\item[{\bf ReturnSocket()}] Deze methode levert de socket terug in; net als een leenboek uit de bibliotheek. De socket wordt door de functie gesloten en opgeschoond. Het resultaat van de sluitoperatie wordt afgeleverd.
\item[{\bf ServerConnection\-ToClient()}] Deze methode zorgt ervoor dat er op een gegeven portnummer geluisterd wordt naar inkomende verbindingen. Als de socket nog niet gebonden is aan een adres of portnummer wordt deze gebonden. Daarna wordt er gewacht tot een cli\"ent met de server verbonden wordt. De \verb|filedescriptor| van de inkomende verbinding wordt door de functie afgeleverd. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\item[{\bf ClientConnection\-ToServer()}] Vergelijkbaar aan de functie \verb|ServerConnectionToClient|. Er wordt nu echter een verbinding naar de server aangemaakt. Als de verbinding door de server geaccepteerd wordt zal de \verb|filedescriptor| van de socket afgeleverd worden. Bij problemen wordt een waarde van \verb|-1| opgeleverd.
\end{description}

\section*{Tweede opdracht: Client en server implementeren}

\subsection*{Implementatie client}
De cli\"ent kan op twee manieren ge\"implementeerd worden; namelijk met een gedeeld proces voor lezen en schrijven van de socket of aparte processen voor het lezen en schrijven van de socket.

Het voordeel van een gedeeld proces voor het lezen en schrijven van de socket is de simpliciteit. Als de cli\"ent ge\"implementeerd kan worden door sequentieel te lezen en te schrijven is een enkel proces een aannemelijke oplossing. Kan het echter gebeuren dat de cli\"ent tijdens een schrijfproces ook tegelijkertijd berichten moet kunnen ontvangen dan is dat niet mogelijk met een gedeeld proces.

De oplossing is het lezen en schrijven naar de socket in aparte processen te draaien. Op deze manier kan tegelijkertijd gelezen en geschreven worden naar de socket. Dit is het voordeel van twee aparte processen. Het nadeel is de verhoogde complexiteit. Bij het afsluiten van de cli\"ent moeten beide processen netjes afgesloten worden en er moet mogelijk gesynchroniseerd kunnen worden tussen beide processen.

Omdat de bulletin-cli\"ent niet tegelijkertijd hoeft te lezen en te schrijven is ervoor gekozen om de cli\"ent in een gedeeld proces te draaien. Bij het opstarten wordt het huidige bulletin van de server uitgelezen. Vervolgens kan de gebruiker achtereenvolgend meerdere berichten naar de server schrijven.

\subsection*{Afsluiten leesproces}
Als het programma gebruik maakt van aparte processen voor het lezen en schrijven van de socket moet er opgelet worden dat het afsluiten van een proces netjes verloopt. In dit voorbeeld wordt aangenomen dat het leesproces afgesloten moet worden in het geval dat er een lees en leesproces gebruikt worden. Er zijn dan twee situatie mogelijk. Het leesproces is een kindproces van het leesproces, of omgekeerd; het leesproces is een ouderproces van het leesproces.

In de eerste situatie waar het leesproces een kindproces is van het leesproces kan het proces simpelweg stopgezet worden. In de tweede situatie kan het leesproces niet zomaar stopgezet worden. Mocht dit gebeuren, dan zou het kindproces niet netje opgeruimd worden. Het ouderproces, in dit geval het leesproces, moet wachten tot de kindprocessen klaar zijn met uitvoeren alvorens zelf stopgezet te worden.

\section*{Derde opdracht: Server als daemon implementeren}
In de methode DaemonService wordt een aangepaste versie van de server geimplementeerd. Alle printf statements uit de server zijn vervangen door LogEvent's. Ook is er een kleine verandering gemaakt in de main functie. Daar wordt het bulletin bestand leeggemaakt.

De TimeStamp code is ook een klein beetje veranderd omdat daar een Y2K bug in zit. Dit is opgelost door de timestamp te vergroten van 18  tekens naar 21  tekens. 
\clearpage

\section*{Broncode}

\subsection*{sockClient.c}

Onderstaande code bevat alleen de code die aan het bestand toegevoegd is.

\begin{verbatim}lees
/* Perform client operation by reading from and writing to the connection */
char str[10];
char str0[128];
int run = 1;

while(run) {
    recv(sock, str0, 10, 0);
    if (strcmp("file_end", str0) == 0)
        break;
    printf("%s", str0);
    bzero(str,10);
}

printf("\n");
run = 1;
while(run) {
    scanf("%s", str);
    if (strcmp("quit", str) == 0)
        break;
    send(sock, str, strlen(str), 0);
}
\end{verbatim}

\subsection*{sockServer.c}

Onderstaande code bevat alleen de code die aan het bestand toegevoegd is.

\begin{verbatim}
/* Service the client by writing to and reading from the connection */
char buf[10];
bzero(buf, 10);
while(fgets(buf, 11 , filer) != NULL) {
    printf("read:[%s]\n",buf);
    int status = send(sock, buf, 10, 0);
    bzero(buf,10);
}
fclose(filer);

int status = send(sock,"file_end", 9 , 0);
printf("status:%i\n", status);

int run = 1;
char str[80];
FILE* filea = fopen("bulletin.txt","a");
while(run == 1) {
    printf("inside loop");
    bzero(str, 80);
    int status = recv(sock, str, 80, 0);
    printf("msg: %s, %i\n",str, status);

    fwrite(str, 1, strlen(str), filea);
    printf("wrote to file\n");
	if (status < 1 || str[0] == 4)
        run = 0;
}
\end{verbatim}

\subsection*{sockDaemon.c}
\begin{verbatim}
int main
{
    ...
    signal(SIGCHLD, SIG_IGN); /* avoid zombies to remain existing */

/* Create server's socket */

    if ((handle = CreateSocket()) == 0) 
        FatalError("Server daemon can't create socket");

/* Open and clear log file for tracing errors */

    if (!fopen(daemonLog, "w"))/* clear traceFile, failure is unreported */;
    FILE* filew = fopen("bulletin.txt", "w");
    fclose(filew);

    LogEvent("hi tiger", 0);
    ...
}

void DaemonService(int sock)
{
    LogEvent("accept connection",0);	
    FILE* filer = fopen("bulletin.txt","r");
    if (filer == NULL)
        FatalError("can't open file");
	
    char buf[10];
    LogEvent("Sending file", 0);
    bzero(buf, 10);
    while(fgets(buf, 10 , filer) != NULL) {
        int status = send(sock, buf, 10, 0);
        LogEvent(buf, 0);
        bzero(buf,10);
    }
    fclose(filer);
    LogEvent("send file",0);
	
    int status = send(sock,"file_end", 9 , 0);
    int run = 1;
    char str[80];
    FILE* filea = fopen("bulletin.txt","a");
    if (filea == NULL)
        FatalError("can't open file to write");	

    while(run == 1) {
        bzero(str, 80);
        int status = recv(sock, str, 80, 0);
		
        fwrite(str, 1, strlen(str), filea);
        if (status < 1 || str[0] == 4)
            run = 0;
    }
    close(sock);
    fclose(filea);
    LogEvent("Come back soon", 0);
}
\end{verbatim}

\end{document}